package com.naiterui.ehp.bs.emr.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.bo.ca.EmrSignBO;
import com.naiterui.ehp.bp.bo.consult.VideoConsultMessageBO;
import com.naiterui.ehp.bp.bo.doctor.RecomDoctorBO;
import com.naiterui.ehp.bp.bo.doctor.RecomPatientBO;
import com.naiterui.ehp.bp.bo.doctor.RecomUserInfoBO;
import com.naiterui.ehp.bp.bo.emr.DrRecordIdBO;
import com.naiterui.ehp.bp.bo.emr.InquireCaseBO;
import com.naiterui.ehp.bp.bo.emr.MedicalRecordBO;
import com.naiterui.ehp.bp.bo.emr.MedicalRecordDoctorBO;
import com.naiterui.ehp.bp.bo.emr.MedicalRecordIdBO;
import com.naiterui.ehp.bp.bo.emr.MedicalRecordRecomBO;
import com.naiterui.ehp.bp.bo.emr.MedicalRecordScreenBO;
import com.naiterui.ehp.bp.bo.emr.RecordRecomIdBO;
import com.naiterui.ehp.bp.bo.emr.RedisRevisitBO;
import com.naiterui.ehp.bp.bo.emr.params.DrCaseParams;
import com.naiterui.ehp.bp.bo.emr.params.RevisitNoticeParamBO;
import com.naiterui.ehp.bp.bo.esign.EsignNoSecretBO;
import com.naiterui.ehp.bp.bo.esign.RecomSignParamBO;
import com.naiterui.ehp.bp.bo.im.DoctorsMedicalRecordBO;
import com.naiterui.ehp.bp.bo.im.MessageSendResultBO;
import com.naiterui.ehp.bp.bo.im.NotifyRevisitBO;
import com.naiterui.ehp.bp.bo.im.RecommandDrugBO;
import com.naiterui.ehp.bp.bo.patient.PatientInquirerBO;
import com.naiterui.ehp.bp.bo.recommend.DiagnosisParamBO;
import com.naiterui.ehp.bp.bo.recommend.PatientDiagnisisBO;
import com.naiterui.ehp.bp.bo.recommend.RecomDiagnosisBO;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.constants.CommonConstant.ConsultType;
import com.naiterui.ehp.bp.constants.InquirerRelationEnum;
import com.naiterui.ehp.bp.support.exception.BaseExceptionCodes;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.JsonException;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.beans.BeanUtil;
import com.naiterui.ehp.bp.utils.biz.NameUtils;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.encypt.AESUtil;
import com.naiterui.ehp.bp.utils.esign.ESignUtils;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bp.utils.lang.File2MultipartFileUtil;
import com.naiterui.ehp.bp.utils.lang.ImageUtil;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bp.utils.net.RestHttpUtil;
import com.naiterui.ehp.bs.emr.config.TreatmentPresetOptionsConfig;
import com.naiterui.ehp.bs.emr.dao.mongo.DrRecordDao;
import com.naiterui.ehp.bs.emr.dto.SignInfoDTO;
import com.naiterui.ehp.bs.emr.entity.mongo.BaseMedicalRecordConsultRoom;
import com.naiterui.ehp.bs.emr.entity.mongo.DoctorInfo;
import com.naiterui.ehp.bs.emr.entity.mongo.ImgFile;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecord;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordConsultRoom;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordDoctor;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordFromPatient;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordRecom;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordScale;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordScreen;
import com.naiterui.ehp.bs.emr.entity.mongo.Menstrual;
import com.naiterui.ehp.bs.emr.entity.mongo.PatientDisease;
import com.naiterui.ehp.bs.emr.entity.mongo.PatientMedicalRecord;
import com.naiterui.ehp.bs.emr.entity.mongo.SessionInfo;
import com.naiterui.ehp.bs.emr.entity.mongo.SignInfo;
import com.naiterui.ehp.bs.emr.entity.mysql.EmrRecordTemplate;
import com.naiterui.ehp.bs.emr.exception.ExceptionCodes;
import com.naiterui.ehp.bs.emr.feign.ESignFeignClient;
import com.naiterui.ehp.bs.emr.feign.IPatientFeignClient;
import com.naiterui.ehp.bs.emr.feign.IRecommendFeignClient;
import com.naiterui.ehp.bs.emr.feign.VideoConsultFeignClient;
import com.naiterui.ehp.bs.emr.remote.IEmrRemoter;
import com.naiterui.ehp.bs.emr.repository.mongo.MedicalRecordRepository;
import com.naiterui.ehp.bs.emr.repository.mongo.PatientDiseaseRepository;
import com.naiterui.ehp.bs.emr.repository.mongo.PatientMedicalRecordRepository;
import com.naiterui.ehp.bs.emr.repository.mysql.IEmrRecordTemplateRepository;
import com.naiterui.ehp.bs.emr.service.IDrCaseService;
import com.naiterui.ehp.bs.emr.service.IMedicalRecordSettingService;
import com.naiterui.ehp.bs.emr.service.IPatientIntelligentLabelService;
import com.naiterui.ehp.bs.emr.utils.Constants;
import com.naiterui.ehp.bs.emr.utils.EmrScaleUtil;
import com.naiterui.ehp.bs.emr.utils.ImageUrlUtil;
import com.naiterui.ehp.bs.emr.utils.LimitValueConfig;
import com.naiterui.ehp.bs.emr.utils.PatientIntelligentLabelUtil;
import com.naiterui.ehp.bs.emr.utils.UserUtil;
import com.naiterui.ehp.bs.emr.vo.AddPatientRecordInitializeVO;
import com.naiterui.ehp.bs.emr.vo.CaseInitVO;
import com.naiterui.ehp.bs.emr.vo.DrCaseInvalidVO;
import com.naiterui.ehp.bs.emr.vo.DrCaseVO;
import com.naiterui.ehp.bs.emr.vo.DrRecordVO;
import com.naiterui.ehp.bs.emr.vo.ImgFileVO;
import com.naiterui.ehp.bs.emr.vo.MCaseFileImgVO;
import com.naiterui.ehp.bs.emr.vo.PatientOrDoctorCaseVO;
import com.naiterui.ehp.bs.emr.vo.RecordPaitentCaseVO;
import com.naiterui.ehp.bs.emr.vo.RecordPrescriptionVO;
import com.naiterui.ehp.bs.emr.vo.RecordTemplateVO;
import com.naiterui.ehp.bs.emr.vo.SaveCaseVO;
import com.naiterui.ehp.bs.emr.vo.SendCaseVO;
import com.naiterui.ehp.bs.emr.vo.amc.AmcResultVO;
import com.naiterui.ehp.bs.emr.vo.amc.ConclusionVO;
import com.naiterui.ehp.bs.emr.vo.patient.MenstrualVO;
import com.naiterui.ehp.bs.emr.vo.patient.SignInfoVO;
import com.naiterui.ehp.bs.emr.vo.scale.DoctorScaleVO;

import cn.hutool.core.collection.CollectionUtil;

@Service
public class DrCaseServiceImpl extends AbstractMedicalRecordServiceImpl implements IDrCaseService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DrCaseServiceImpl.class);

    /**
     * 复诊时间key
     */
    private static final String NOTIFY_REVISIT_RECORDID_KEY = CommonConstant.REDIS_PRE_EMR + "revisit_record_key";

    private static final String EHP_HOSPITAL_NAME = ConfigUtil.getString("ehp.hospital.name");
    /**
     * 医生病历全部祥情
     */
    private static final int DR_RECORD_ALL = 1;
    /**
     * 医生病历子祥情
     */
    private static final int DR_RECORD_SON = 2;
    /**
     * 患者发送病历全部祥情
     */
    private static final int PT_RECORD_ALL = 1;
    /**
     * 患者发送病历子祥情
     */
    private static final int PT_RECORD_SON = 2;
    /**
     * 患者线上诊室病历全部祥情
     */
    private static final int PT_CONSULT_ROOM_ALL = 1;
    /**
     * 患者线上诊室病历子祥情
     */
    private static final int PT_CONSULT_ROOM_SON = 2;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IEmrRemoter remoter;
    @Autowired
    private DrRecordDao drRecordDao;
    @Autowired
    private MedicalRecordRepository medicalRecordRepository;
    @Autowired
    private PatientMedicalRecordRepository patientMedicalRecordRepository;
    @Autowired
    private PatientDiseaseRepository patientDiseaseRepository;
    @Autowired
    private IPatientIntelligentLabelService patientIntelligentLabelService;
    @Autowired
    private IEmrRecordTemplateRepository emrRecordTemplateRepository;

    @Autowired
    private ESignFeignClient eSignFeignClient;
    @Autowired
    private IRecommendFeignClient recommendFeignClient;
    @Autowired
    private IPatientFeignClient patientFeignClient;
    @Autowired
    private VideoConsultFeignClient videoConsultFeignClient;

    @Autowired
    private TreatmentPresetOptionsConfig optionsConfig;

    @Autowired
    private IMedicalRecordSettingService medicalRecordSettingService;

    @Override
    public CaseInitVO initCase(Long doctorId, Long patientId, Long inquirerId) throws BusinessException {
        CaseInitVO caseInitVO = new CaseInitVO();
        List<String> options = optionsConfig.getOptions().stream().collect(Collectors.toList());
        caseInitVO.setTreatmentPresetOptions(options);
        // 医生信息和医生备注患者信息
        RecomUserInfoBO recomUserInfoBO = remoter.getUserInfo(doctorId, patientId, true);
        if (recomUserInfoBO == null) {
            LOGGER.warn("医生信息和医生备注患者信息为null,doctorId:{},patient:{}", doctorId, patientId);
            throw new BusinessException(ExceptionCodes.FAILED);
        }
        RecomDoctorBO doctorBO = recomUserInfoBO.getDoctor();
        RecomPatientBO patientBO = recomUserInfoBO.getPatient();
        caseInitVO.setDoctorName(doctorBO.getName());
        //String hospitalName = doctorBO.getHospitalName();
        caseInitVO.setHospital(EHP_HOSPITAL_NAME);
        //String departmentName = doctorBO.getDepartmentName();
        //改成一级科室
        caseInitVO.setDepartment(UserUtil.getOneDepartName(doctorBO));
        Integer status = patientBO.getStatus();
        //获取就诊人信息
        List<PatientInquirerBO> inquirerBOS = patientFeignClient.getPatientInquirer(Lists.newArrayList(inquirerId));
        if (CollectionUtils.isEmpty(inquirerBOS)) {
            LOGGER.error("就诊人信息不存在：inquirerId={}", inquirerId);
            throw new BusinessException(ExceptionCodes.FAILED);
        }
        PatientInquirerBO inquirerBO = inquirerBOS.get(0);
        String patientName = inquirerBO.getName();
        caseInitVO.setName(NameUtils.handleUtf8mb4(patientName, ""));
        caseInitVO.setGender(inquirerBO.getGender());
        caseInitVO.setAge(inquirerBO.getAgeYear());
        caseInitVO.setAgeUnit("岁");
        caseInitVO.setAgeStr(inquirerBO.getAge());
        // 主诉、现病史、既往史必填控制标识1必2非必(2.19之后弃用)
        caseInitVO.setRequiredFlag(Integer.parseInt(ConfigUtil.getString("main.complaint.flag")));
        // 患者发送最近本人病历
        MedicalRecord medicalRecord = drRecordDao.getPatientSendLateCase(doctorId, patientId);
        if (medicalRecord == null) {
            return caseInitVO;
        }
        // 病历类型
        caseInitVO.setCaseType(medicalRecord.getCaseType());
        // 患者普通病历
        if (medicalRecord.getCaseType() == MedicalRecord.CASETYPE_PATIENTRECORD) {
            if (medicalRecord.getRecordPatient() != null) {
                MedicalRecordFromPatient recordPatient = medicalRecord.getRecordPatient();
                caseInitVO.setDescription(recordPatient.getDescription());// 病情描述
                caseInitVO.setAmcResult(recordPatient.getAmcResult());
                // 清空预诊建议(前端后来不需要显示)
                if (caseInitVO.getAmcResult() != null) {
                    caseInitVO.getAmcResult().setConclusions(null);
                }
                // 处理换行和回车
                this.handleAmc(caseInitVO.getAmcResult());
                // 是否孕期
                if (recordPatient.getPregnancy() != null) {
                    if (RecordPaitentCaseVO.EPregnancy.val(recordPatient.getPregnancy()) != null) {
                        caseInitVO.setPregnancy(RecordPaitentCaseVO.EPregnancy.val(recordPatient.getPregnancy()).getName());
                    }
                }
                caseInitVO.setHeight(recordPatient.getHeight());
                caseInitVO.setWeight(recordPatient.getWeight());
                caseInitVO.setMedicAllergys(recordPatient.getMedicAllergysStr());// 过敏药物
                caseInitVO.setPastDiseases(recordPatient.getPastDiseasesStr());// 过往病史
                caseInitVO.setFamilyDiseases(recordPatient.getFamilyDiseasesStr());// 家族病史
                caseInitVO.setHereditaryDiseases(recordPatient.getHereditaryDiseasesStr());// 遗传病
                caseInitVO.setSmoke(recordPatient.getSmokeStr());// 吸烟情况
                caseInitVO.setDrink(recordPatient.getDrinkStr());// 饮酒情况
            } else {
                LOGGER.warn("患者发送病历无子对象,recordId:{}", medicalRecord.getId());
            }
        }// 线上诊室病历
        else if (medicalRecord.getCaseType() == MedicalRecord.CASETYPE_CONSULT) {
            caseInitVO.setDrCaseVO(this.handleConsultRoom(medicalRecord.getRecordConsult(), medicalRecord, PT_CONSULT_ROOM_ALL));
        }
        return caseInitVO;
    }

    @Override
    public List<String> uploadFiles(Long doctorId, MultipartFile[] files) throws BusinessException {
        List<String> list = new ArrayList<>();
        try {
            String params = doctorId + "";
            for (MultipartFile file : files) {
                String url = ImageUtil.getUri(ImageUtil.upload(Constants.RECORD_TYPE, file, params), Constants.RECORD_TYPE);
                list.add(url);
            }
        } catch (Exception e) {
            LOGGER.error("图片上传错误,doctorId:{}", doctorId, e);
            throw new BusinessException(ExceptionCodes.FAILED, e);
        }

        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SaveCaseVO saveDrMedicalRecord(DrCaseParams params, Boolean send, Integer requestFrom)
        throws BusinessException {
        SaveCaseVO saveCaseVO = new SaveCaseVO();
        // 验证并装配数据
        MedicalRecord medicalRecord = this.drCaseToMedicalRecord(params);

        // 保存病历
        medicalRecordRepository.save(medicalRecord);
        // 判断病历页筛选条件是否已存在
        super.saveMedicalRecordScreen(medicalRecord);
        LOGGER.info("保存病例成功：recordId={}", medicalRecord.getId());

        //判断当前是否需要签名——默认开启
        if (!RedisUtil.keyOps().existsKey(Constants.EMR_SIGN_SWITCH_KEY)) {
            LOGGER.info("强制签名已开启：recordId={}", medicalRecord.getId());
            if (requestFrom != RecomSignParamBO.REQUEST_FROM_PC) {
                // 是否免签
                EsignNoSecretBO noSecretInfo = eSignFeignClient.getNoSecretInfo(params.getDoctorId());
                requestFrom =
                    noSecretInfo.getNoSecret() ? RecomSignParamBO.REQUEST_FROM_SYSTEM
                        : RecomSignParamBO.REQUEST_FROM_APP;
            }
            //需要签名则调用签名服务获签名信息
            EmrSignBO signBO =
                eSignFeignClient.getSignInfo(medicalRecord.getId(), medicalRecord.getInquirerId(), requestFrom);
            LOGGER.info("获取预签名成功：signBO={}", signBO.toString());
            List<SignInfo.FileInfo> files = new ArrayList<>();
            files.add(SignInfo.FileInfo.builder()
                .path(signBO.getFilePath())
                .time(new Date())
                .type(SignInfo.FILE_TYPE_DEFAULT)
                .build());
            //保存签名和文件信息
            medicalRecord.setSignInfo(SignInfo.builder()
                .unionId(signBO.getUniqueId())
                .files(files)
                .signFlag(SignInfo.SIGN_FLAG_DEFAULT)
                .build());

            saveCaseVO.setUniqueId(signBO.getUniqueId());
            saveCaseVO.setFaceUrl(signBO.getFaceUrl());

            //固话签名开关_开启
            medicalRecord.setSignSwitch(MedicalRecord.SIGN_SWITCH_ON);
        } else {
            //固话签名开关_关闭
            medicalRecord.setSignSwitch(MedicalRecord.SIGN_SWITCH_OFF);
        }

        // 更新病历
        medicalRecordRepository.update(medicalRecord);

        RedisUtil.hashOps()
            .hset(CommonConstant.CONSULT_MEDICAL_RECORD_EXIST, params.getPatientId() + "_" + params.getDoctorId(), medicalRecord.getId());

        saveCaseVO.setRecordId(medicalRecord.getId());
        try {
            recommendFeignClient.getDiagnosisList(DiagnosisParamBO.builder().doctorId(params.getDoctorId()).diagnosis(params.getDiagnosisList()).build());
        }catch (Exception e){
            LOGGER.warn("添加病历更新常用诊断失败 doctorId:{}, diagnosisList:{}, ex:{}", params.getDoctorId(), params.getDiagnosisList(), e.getMessage());
        }
        return saveCaseVO;
    }

    @Override
    public void sign(String recordId, Long doctorId, String uniqueId, String pin, Integer requestFrom)
        throws BusinessException {
        MedicalRecord medicalRecord = medicalRecordRepository.get(recordId);
        if (medicalRecord == null) {
            throw new BusinessException(ExceptionCodes.RECORD_NOT_EXIST);
        }
        // 是否免签
        EsignNoSecretBO noSecretInfo = eSignFeignClient.getNoSecretInfo(doctorId);
        if (noSecretInfo.getNoSecret()) {
            requestFrom = RecomSignParamBO.REQUEST_FROM_SYSTEM;
            pin = StringUtils.isBlank(noSecretInfo.getPin()) ? null
                    : AESUtil.decrypt(CommonConstant.ESIGN_NO_SECRET_KEY, noSecretInfo.getPin());
        }

        //调用签名,签名结果回调方式实现
        eSignFeignClient.sign(recordId, pin, requestFrom);
    }

    @Override
    public SendCaseVO confirm(String caseId, Long doctorId, Boolean force, Integer consultType, Long consultId, Boolean send)
        throws BusinessException {
        if (consultType == null) {
            consultType = ConsultType.GRAPHIC;
        }

        MedicalRecord medicalRecord = medicalRecordRepository.get(caseId);
        DoctorsMedicalRecordBO doctorsMedicalRecordBO;
        SendCaseVO sendCaseVO = new SendCaseVO();

        SessionInfo sessionInfo = new SessionInfo();
        sessionInfo.setForce(SessionInfo.FORCE_NO);

        //签名失败并强制推送
        if (force != null && force) {
            sessionInfo.setForce(SessionInfo.FORCE_YES);
        }

        Criteria criteria = Criteria.where("id").is(caseId);
        Query query = new Query(criteria);
        Update update = new Update();

        //签名信息
        SignInfo signInfo = medicalRecord.getSignInfo();
        if (signInfo == null) {
            throw new BusinessException(ExceptionCodes.SIGN_ERR);
        }

        if (send) {

            LOGGER.info("发送病例：caseId={}, send={}", caseId, send);
            try {
                doctorsMedicalRecordBO = this.buildImRecordMessage(medicalRecord);
                // 患者病历id_修改为医生端病例id,兼容前端
                doctorsMedicalRecordBO.setPatientsMedicalRecordId(medicalRecord.getId());
            } catch (Exception e) {
                LOGGER.error("发送病历拼装消息数据异常", e);
                throw new BusinessException(ExceptionCodes.FAILED, e);
            }
            try {
                doctorsMedicalRecordBO.setConsultType(consultType);
                MessageSendResultBO resultBO = remoter.sendDoctorRecord(doctorsMedicalRecordBO);
                BeanUtils.copyProperties(resultBO, sendCaseVO);
                if(ConsultType.GRAPHIC == consultType){
                    sessionInfo.setSessionId(resultBO.getSessionId());
                    sessionInfo.setSendTime(new Date(resultBO.getSendTime()));
                    update.set("sessionInfo", sessionInfo);
                }
                //记录发送消息
                LOGGER.info("调用IM发送病例成功： resultBO={}", resultBO.toString());
            } catch (Exception e) {
                LOGGER.error("调用IM发送病历异常", e);
                throw new BusinessException(ExceptionCodes.FAILED, e);
            }
            //            medicalRecord.setSessionInfo(sessionInfo);
            //            // 已发送标识
            //            medicalRecord.setSend(MedicalRecord.SEND_YES);
            update.set("send", MedicalRecord.SEND_YES);
        }

        //        medicalRecord.setChangeAt(new Date());
        //        medicalRecordRepository.update(medicalRecord);
        update.set("changedAt", new Date());
        //指定字段更新，避免被签名回调覆盖
        mongoTemplate.updateFirst(query, update, MedicalRecord.class);

        sendCaseVO.setRecordId(medicalRecord.getId());

        //更新患者诊断
        recommendFeignClient.updateDiagnosis(
            PatientDiagnisisBO.builder()
                .doctorId(medicalRecord.getDoctorId())
                .patientId(medicalRecord.getPatientId())
                .inquirerId(medicalRecord.getInquirerId())
                .diagnosis(medicalRecord.getRecordDoctor().getDiagnosisList())
                .build());

        //视频问诊
        if (ConsultType.VIDEO == consultType && consultId != null) {
            try {
                //保存视频问诊病历记录
                videoConsultFeignClient.saveVideoConsultMessage(VideoConsultMessageBO.builder()
                    .videoConsultId(consultId)
                    .doctorId(medicalRecord.getDoctorId())
                    .patientId(medicalRecord.getPatientId())
                    .inquirerId(medicalRecord.getInquirerId())
                    .type(VideoConsultMessageBO.VIDEO_CONSULT_TYPE_TO_DRCASE)
                    .content(medicalRecord.getId())
                    .build());
            } catch (Exception e) {
                LOGGER.error("保存视频问诊病历记录：ERROR ;", e);
            }

        }

        LOGGER.info("病例确认成功：sendCaseVO={}", sendCaseVO.toString());
        return sendCaseVO;
    }

    @Override
    public void updateSignInfo(EmrSignBO bo) throws BusinessException {
        MedicalRecord record = medicalRecordRepository.get(bo.getId());
        SignInfo signInfo = record.getSignInfo();
        if (bo.getStatus() == EmrSignBO.SIGN_STATUS_SUCCESS) {
            signInfo.setSignFlag(SignInfo.SIGN_FLAG_SUCCESS);
        } else {
            signInfo.setSignFlag(SignInfo.SIGN_FLAG_FAIL);
        }
        signInfo.setSignTime(bo.getCreatedAt());
        signInfo.setDoctorName(record.getDoctorName());
        signInfo.setHospitalName(EHP_HOSPITAL_NAME);
        signInfo.setSealImage(bo.getSealImage());

        signInfo.getFiles().add(SignInfo.FileInfo.builder()
            .path(bo.getFilePath())
            .type(SignInfo.FILE_TYPE_SIGN)
            .time(bo.getCreatedAt())
            .build());
        //        record.setSignInfo(signInfo);
        //        LOGGER.info("保存签名信息：signinof={}", signInfo.toString());
        //        medicalRecordRepository.update(record);
        //        LOGGER.info("更新签名信息成功");

        //更新签名信息，指定字段更新，避免被confirm方法覆盖
        Criteria criteria = Criteria.where("id").is(bo.getId());
        Query query = new Query(criteria);
        Update update = new Update();
        update.set("signInfo", signInfo);
        mongoTemplate.updateFirst(query, update, MedicalRecord.class);
    }

    /**
     * 存放redis复诊时间和复诊对象(复诊通知会用) DrCaseServiceImpl.setRecordKey()
     *
     * @param medicalRecord
     * @Author lichaopi
     * @Date 2018年6月1日
     * @since 1.0.0
     */
    private void setRecordKey(MedicalRecord medicalRecord) throws Exception {
        MedicalRecordDoctor medicalRecordDoctor = medicalRecord.getRecordDoctor();
        if (medicalRecordDoctor.getRevisitFalg() == MedicalRecordDoctor.REVISITFALG_YES) {// 有复诊时间
            RedisRevisitBO redisRevisitBO = new RedisRevisitBO();
            redisRevisitBO.setId(medicalRecord.getId());
            redisRevisitBO.setDoctorId(medicalRecord.getDoctorId());
            Long patientId = medicalRecord.getPatientId();
            redisRevisitBO.setPatientId(patientId);
            redisRevisitBO.setPatientName(medicalRecord.getName());
            redisRevisitBO.setDoctorName(medicalRecord.getDoctorName());
            String boStr = JSON.toJSONString(redisRevisitBO);
            Date date = medicalRecordDoctor.getRevisitDate();
            String partKey = DateUtil.formatDate(date, DateUtil.DATE_FORMAT);
            RedisUtil.listOps().rpush(NOTIFY_REVISIT_RECORDID_KEY + partKey, boStr);

            // 删除复诊提醒记录
            remoter.asyncDelRebuyNotice(patientId, date);
        }
    }

    /**
     * 装配好的对象 DrCaseServiceImpl.drCaseToMedicalRecord()
     *
     * @return
     * @throws BusinessException
     * @Author lichaopi
     * @Date 2018年5月30日
     * @since 1.0.0
     */
    private MedicalRecord drCaseToMedicalRecord(DrCaseParams params) throws BusinessException {
        // 查询医生信息
        Long doctorId = params.getDoctorId();
        Long patientId = params.getPatientId();
        RecomUserInfoBO remoterUserInfo = remoter.getUserInfo(doctorId, patientId, true);
        if (remoterUserInfo == null) {
            LOGGER.error("医生信息和医生备注患者信息为null,doctorId:{},patient:{}", doctorId, patientId);
            throw new BusinessException(ExceptionCodes.FAILED);
        }
        RecomDoctorBO doctorBO = remoterUserInfo.getDoctor();
        // 验证数据
        this.verifyMedicalRecord(params, doctorBO);

        //获取就诊人信息
        List<PatientInquirerBO> inquirerBOS = patientFeignClient.getPatientInquirer(Lists.newArrayList(params.getInquirerId()));
        if (CollectionUtils.isEmpty(inquirerBOS)) {
            LOGGER.error("就诊人信息不存在：inquirerId={}", params.getInquirerId());
            throw new BusinessException(ExceptionCodes.FAILED);
        }
        PatientInquirerBO patientBO = inquirerBOS.get(0);
        Integer relation = patientBO.getRelation();
        String patientName = patientBO.getName();
        Integer patientGender = patientBO.getGender();
        Integer patientAge = patientBO.getAgeYear();
        String patientAgeStr = patientBO.getAge();
        String contactName = patientBO.getContactName();
        String contactPhone = patientBO.getContactPhone();
        // 判断医生病历类型和暂存状态
        int caseType = MedicalRecord.CASETYPE_DOCTORRECORD;// 不带处方病历
        Integer temporary = null;// 暂存标识
        if (params.getRecommendId() != null) {
            caseType = MedicalRecord.CASETYPE_DOCTORRECORD_RECOM;// 带处方病历
            temporary = MedicalRecord.TEMPORARY_YES;// 暂存
        }
        // 基本信息
        String doctorBOName = doctorBO.getName();
        //String departmentName = doctorBO.getDepartmentName();
        String hospitalName = doctorBO.getHospitalName();

        // 装配病历子对象
        // 复诊时间
        Date revisitDate = null;
        Integer revisitNumber = null;
        String revisitDateUnit = null;
        if (params.getRevisitFalg() == MedicalRecordDoctor.REVISITFALG_YES) {// 有复诊时间
            revisitNumber = params.getRevisitNumber();
            revisitDateUnit = params.getRevisitDateUnit();
            Integer day = params.getRevisitNumber();
            if (MedicalRecordDoctor.DATE_UNTI_WEKK.equals(params.getRevisitDateUnit())) {
                day = day * 7;
            } else if (MedicalRecordDoctor.DATE_UNTI_MONTH.equals(params.getRevisitDateUnit())) {
                day = day * 30;
            }
            Date nowDate = new Date();
            Calendar cl = Calendar.getInstance();
            cl.setTime(nowDate);
            cl.add(Calendar.DATE, day);
            revisitDate = cl.getTime();
        }
        // 图片处理（有可能是别的病历图片带过来的）
        List<String> imgStrList;
        try {
            imgStrList = this.handleImgList(doctorId, params.getImgList());
        } catch (Exception e) {
            LOGGER.warn("图片处理异常", e);
            throw new BusinessException(ExceptionCodes.FAILED, e);
        }

        // 图片加uuid
        List<ImgFile> imgList = Optional.ofNullable(imgStrList)
            .orElse(Lists.newArrayList())
            .stream()
            .map(s -> {
                String uuid = StringUtil.formatUUID();
                ImgFile img = new ImgFile();
                img.setUuid(uuid);
                img.setUrl(s);
                return img;
            }).collect(Collectors.toList());

        // 诊断处理
        List<String> diagnosisList = params.getDiagnosisList();

        //量表编号处理
        MedicalRecordScale scale = null;
        if (params.getExtBizId() != null) {
            scale = new MedicalRecordScale();
            String extBizId = EmrScaleUtil.handleExtBizId(params.getExtBizId());
            scale.setExtBizId(extBizId);
        }
        //查询模板名称
        Long templateId = params.getTemplateId();
        String templateName = null;
        if (templateId != null) {
            EmrRecordTemplate template = emrRecordTemplateRepository.get(params.getTemplateId());
            if (template == null) {
                LOGGER.info("查询模板对象为空,templateId:{}", templateId);
                throw new BusinessException(ExceptionCodes.EMR_RECORD_TEMPLATE_NO_EXIST);
            }
            templateName = template.getName();

        }

        // 月经信息
        Menstrual menstrual =
            Menstrual.builder()
                .cycle(params.getCycle())
                .dysmenorrhea(params.getDysmenorrhea())
                .firstAge(params.getFirstAge())
                .part(params.getPart())
                .processDays(params.getProcessDays())
                .status(params.getStatus())
                .build();

        // 医生病历信息
        MedicalRecordDoctor medicalRecordDoctor = MedicalRecordDoctor.builder()
            .mainComplaint(params.getMainComplaint())
            .presentDisease(params.getPresentDisease())
            .pastHistory(params.getPastHistory())
            .temperature(params.getTemperature())
            .weight(params.getWeight())
            .heartRete(params.getHeartRete())
            .systolic(params.getSystolic())
            .diastole(params.getDiastole())
            .moreExamin(params.getMoreExamin())
            .alt(params.getAlt())
            .ast(params.getAst())
            .hbvDna(params.getHbvDna())
            .diagnosisList(diagnosisList)
            .doctorOrder(params.getDoctorOrder())
            .revisitFalg(params.getRevisitFalg())
            .revisitNumber(revisitNumber)
            .revisitDateUnit(revisitDateUnit)
            .revisitDate(revisitDate)
            .imgList(imgList)
            .templateType(params.getTemplateType())
            .templateId(params.getTemplateId())
            .scale(scale)
            .templateName(templateName)
            .treatmentOptions(params.getTreatmentOptions())
            .menstrual(menstrual)
            .positiveSigns(params.getPositiveSigns())
            .negativeSigns(params.getNegativeSigns())
            .allergy(params.getAllergy())
            .pastFamily(params.getPastFamily())
            .contactName(contactName)
            .contactPhone(contactPhone)
            .build();
        // 设置处方对象
        if (params.getRecommendId() != null) {
            MedicalRecordRecom recom = new MedicalRecordRecom();
            recom.setRecommendId(params.getRecommendId());
            recom.setInvalid(MedicalRecordRecom.INVALID_STATUS_NORMAL);
            medicalRecordDoctor.setRecom(recom);
        }

        List<DoctorInfo> doctors = new ArrayList<>();
        //医生信息：设置医生为创建者_海南版本_病例以患者维度归档
        doctors.add(DoctorInfo.builder()
            .doctorId(doctorId)
            .title(doctorBO.getTitle())
            .doctorName(doctorBOName)
            .departmentName(UserUtil.getOneDepartName(doctorBO))
            .hospitalName(hospitalName)
            .role(DoctorInfo.ROLE_CREATER)
            .build());

        return MedicalRecord.builder()
            .doctorId(doctorId).doctorName(doctorBOName).department(UserUtil.getOneDepartName(doctorBO))
            .hospitalName(hospitalName).patientId(patientId).inquirerId(params.getInquirerId()).name(patientName)
            .gender(null == patientGender ? params.getPatientGender() : patientGender).age(patientAge).ageUnit("岁")
            .ageStr(patientAgeStr).caseType(caseType).relation(relation)
            // 暂存标识
            .temporary(temporary)
            // 医生职称
            .title(doctorBO.getTitle())
            // 病历状态
            .invalid(MedicalRecord.INVALID_STATUS_NORMAL).recordDoctor(medicalRecordDoctor)
            // 保存病历设置
            .medicalRecordSettingList(this.medicalRecordSettingService.listByDoctorId(doctorId))
            .createAt(new Date()).changeAt(new Date()).createBy(doctorBOName).changeBy(doctorBOName)
            // 设置医生信息
            .doctors(doctors).build();
    }

    /**
     * 验证数据准确性 DrCaseServiceImpl.verifyMedicalRecord()
     *
     * @throws BusinessException
     * @since 1.0.0
     */
    private void verifyMedicalRecord(DrCaseParams drCaseParams, RecomDoctorBO doctorBO) throws BusinessException {
        // 验证患者姓名
        String patientName = drCaseParams.getPatientName();
        LimitValueConfig.validationString(LimitValueConfig.LIMIT_PATIENT_NAME, patientName);

        // 将中文标点符号替换为英文标点符号 from V2.9.2(保存处方中引过来的)
        patientName = NameUtils.replaceChinesePunctuation(patientName);

        if (!patientName.trim().matches(NameUtils.VALIDATE_REGEX_USER_NAME)) {
            LOGGER.warn("患者姓名包含特殊字符: patientName:{}", patientName);
            throw new BusinessException(ExceptionCodes.DOCTOR_RECOM_PATIENT_NAME_INPUT_INVALID);
        }
        drCaseParams.setPatientName(patientName);
        // 验证性别
        Integer gender = drCaseParams.getPatientGender();
        MedicalRecord.GenderEnum gEnum = MedicalRecord.GenderEnum.val(gender);
        if (gEnum == null) {
            LOGGER.warn("患者性别不合法,gender : {}", gender);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        // 验证年龄
        Integer patientAge = drCaseParams.getAge();
        //        LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_PATIENT_AGE, patientAge);

        // 校验输入的年龄单位，允许的值（周，个月，岁）
        String ageUnit = drCaseParams.getAgeUnit();
        //        if (MedicalRecord.AgeUnitEunm.val(ageUnit) == null) {
        //            LOGGER.warn("患者性别不合法,gender : {}", gender);
        //            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        //        }
        // 诊断非空验证
        if (drCaseParams.getRecommendId() != null) {// 有推荐id时诊断必填
            if (drCaseParams.getDiagnosisList() == null || drCaseParams.getDiagnosisList().isEmpty()) {
                LOGGER.warn("有推荐id,诊断必填,recomId:{}", drCaseParams.getRecommendId());
                throw new BusinessException(ExceptionCodes.PARAM_ERROR);
            }
        }
        //如果是灰度医生需要返回icd10诊断
        if (doctorBO.getLabel().getDiagnosis() && drCaseParams.getDiagnosisList() != null && !drCaseParams.getDiagnosisList().isEmpty()) {
            RecomDiagnosisBO diagnosisBO = remoter.getRecomICD10(drCaseParams.getDiagnosisList());
            List<String> diagnosisList = diagnosisBO.getDiagnosis();
            if (diagnosisList == null || diagnosisList.isEmpty() || diagnosisList.size() != drCaseParams.getDiagnosisList().size()) {
                LOGGER.warn("保存病历，灰度医生不可以选择非标准诊断");
                throw new BusinessException(ExceptionCodes.ICD10_DIAGNOSIS_SELECT);
            }
        }
        // 主诉、现病史、既往史必填标识1必0非
        int requFalg = Integer.parseInt(ConfigUtil.getString("main.complaint.flag"));
        // 验证主诉和现病史
        String mainCom = drCaseParams.getMainComplaint();
        String presentD = drCaseParams.getPresentDisease();
        LOGGER.info("主诉原始输入: mainCom:{} 现病史原始输入: presentD:{}", mainCom, presentD);
        // if (StringUtils.isAllBlank(mainCom) && requFalg == CaseInitVO.REQUIRED_YES) {
        // LOGGER.warn("主诉为空: mainCom:{}", mainCom);
        // throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        // }
        // 表情处理
        if (StringUtils.isNotBlank(mainCom)) {
            mainCom = NameUtils.handleUtf8mb4(mainCom.trim(), "");
            // if (!LimitValueConfig.validateLimit(LimitValueConfig.LIMIT_DISEASE_MAINCOMPLAINT, mainCom)) {
            // LOGGER.warn("患者主诉长度不符合规定,mainCom : {}", mainCom);
            // throw new BusinessException(ExceptionCodes.INVALID_CONTENT_LENGTH);
            // }
            drCaseParams.setMainComplaint(mainCom);
        } else {
            drCaseParams.setMainComplaint(null);
        }
        //        if (StringUtils.isNotBlank(presentD)) {
        //            presentD = NameUtils.handleUtf8mb4(presentD.trim(), "");
        //            if (!LimitValueConfig.validateLimit(LimitValueConfig.LIMIT_DISEASE_PRESENTDISEASE, presentD)) {
        //                LOGGER.warn("患者现病史长度不符合规定,presentD : {}", presentD);
        //                throw new BusinessException(ExceptionCodes.INVALID_CONTENT_LENGTH);
        //            }
        //            drCaseParams.setPresentDisease(presentD);
        //        } else {
        //            drCaseParams.setPresentDisease(null);
        //        }
        //现病史
        drCaseParams.setPresentDisease(presentD);
        // 验证既往史
        String pastHistory = drCaseParams.getPastHistory();
        LOGGER.info("既往史原始输入: pastHistory:{}", pastHistory);
//        if (StringUtils.isBlank(pastHistory) && requFalg == CaseInitVO.REQUIRED_YES) {
//            LOGGER.warn("既往史为空: pastHistory:{}", pastHistory);
//            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
//        }
        if (StringUtils.isNotBlank(pastHistory)) {
            pastHistory = NameUtils.handleUtf8mb4(pastHistory.trim(), null);
            if (!LimitValueConfig.validateLimit(LimitValueConfig.LIMIT_DISEASE_PAST, pastHistory)) {
                LOGGER.warn("患者既往史长度不符合规定,pastHistory : {}", pastHistory);
                throw new BusinessException(ExceptionCodes.INVALID_CONTENT_LENGTH);
            }
            drCaseParams.setPastHistory(pastHistory);
        } else {
            drCaseParams.setPastHistory(null);
        }

        // 体温
        Double temperature = drCaseParams.getTemperature();
        if (temperature != null) {
            LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_TEMPERATURE, temperature);
        }
        // 体重
        Double weight = drCaseParams.getWeight();
        if (weight != null) {
            LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_WEIGHT, weight);
        }
        // 心率
        Integer heartRete = drCaseParams.getHeartRete();
        if (heartRete != null) {
            LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_HEARTRETE, heartRete);
        }
        // 收缩压
        Integer systolic = drCaseParams.getSystolic();
        if (systolic != null) {
            LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_SYSTOLIC, systolic);
        }
        // 舒张压
        Integer diastole = drCaseParams.getDiastole();
        if (diastole != null) {
            LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_DIASTOLE, diastole);
        }
        // 更多检查
        String moreExamin = drCaseParams.getMoreExamin();
        if (StringUtils.isNotBlank(moreExamin)) {
            moreExamin = NameUtils.handleUtf8mb4(moreExamin.trim(), "");
            LimitValueConfig.validationString(LimitValueConfig.LIMIT_DISEASE_MOREEXAMINE, moreExamin);
            drCaseParams.setMoreExamin(moreExamin);
        } else {
            drCaseParams.setMoreExamin(null);
        }
        //验证模板
        if (Objects.equals(drCaseParams.getTemplateType(), MedicalRecordDoctor.TEMPLATE_TYPE_HEPATOPATHY)) {
            // alt
            Integer alt = drCaseParams.getAlt();
            if (alt != null) {
                LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_ALT, alt);
            }
            // ast
            Integer ast = drCaseParams.getAst();
            if (ast != null) {
                LimitValueConfig.validationNumber(LimitValueConfig.LIMIT_DISEASE_AST, ast);
            }
            // hbvDna
            String hbvDna = drCaseParams.getHbvDna();
            if (StringUtils.isNotBlank(hbvDna)) {
                hbvDna = NameUtils.handleUtf8mb4(hbvDna.trim(), "");
                LimitValueConfig.validationString(LimitValueConfig.LIMIT_DISEASE_HBV_DNA, hbvDna);
                drCaseParams.setHbvDna(hbvDna);
            } else {
                drCaseParams.setHbvDna(null);
            }
            drCaseParams.setExtBizId(null);
        } else if (Objects.equals(drCaseParams.getTemplateType(), MedicalRecordDoctor.TEMPLATE_TYPE_COMMON)) {
            drCaseParams.setAst(null);
            drCaseParams.setAlt(null);
            drCaseParams.setHbvDna(null);
            drCaseParams.setExtBizId(null);
        } else if (Objects.equals(drCaseParams.getTemplateType(), MedicalRecordDoctor.TEMPLATE_TYPE_SCALE)) {
            drCaseParams.setAst(null);
            drCaseParams.setAlt(null);
            drCaseParams.setHbvDna(null);
            if (drCaseParams.getTemplateId() == null) {
                LOGGER.warn("模板类型为量表类型，模板id必传");
                throw new BusinessException(ExceptionCodes.PARAM_ERROR);
            }
        } else {
            LOGGER.warn("模板类型错误,template:{}", drCaseParams.getTemplateType());
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        //模板id和模板类型作验证
        if (drCaseParams.getTemplateId() != null) {
            EmrRecordTemplate template = emrRecordTemplateRepository.get(drCaseParams.getTemplateId());
            if (template == null) {
                LOGGER.info("查询模板对象为空,templateId:{}", drCaseParams.getTemplateId());
                throw new BusinessException(ExceptionCodes.EMR_RECORD_TEMPLATE_NO_EXIST);
            }
            if (template.getType().intValue() != drCaseParams.getTemplateType().intValue()) {
                LOGGER.info("模板id和模板类型不匹配");
                throw new BusinessException(ExceptionCodes.TEMPLATE_ID_TYPE_NOT_MATCH);
            }


        }
        // 医嘱小结
        String doctorOrder = drCaseParams.getDoctorOrder();
        if (StringUtils.isNotBlank(doctorOrder)) {
            doctorOrder = NameUtils.handleUtf8mb4(doctorOrder.trim(), "");
            LimitValueConfig.validationString(LimitValueConfig.LIMIT_DISEASE_DOCTORORDER, doctorOrder);
            drCaseParams.setDoctorOrder(doctorOrder);
        } else {
            drCaseParams.setDoctorOrder(null);
        }
        if (drCaseParams.getRevisitFalg() == MedicalRecordDoctor.REVISITFALG_YES) {
            String revisitDateUnit = drCaseParams.getRevisitDateUnit();
            if (drCaseParams.getRevisitNumber() == null || revisitDateUnit == null) {
                LOGGER.warn("复诊天数或单位为空,revisitNumber:{},revisitDateUnit:{}", drCaseParams.getRevisitNumber(), revisitDateUnit);
                throw new BusinessException(ExceptionCodes.PARAM_ERROR);
            }
            if (!MedicalRecordDoctor.DATE_UNTI_WEKK.equals(revisitDateUnit)
                && !MedicalRecordDoctor.DATE_UNTI_DAY.equals(revisitDateUnit)
                && !MedicalRecordDoctor.DATE_UNTI_MONTH.equals(revisitDateUnit)) {
                LOGGER.warn("复诊单位不符合规范,revisitDateUnit:{}", revisitDateUnit);
                throw new BusinessException(ExceptionCodes.PARAM_ERROR);
            }
        }
    }

    @Override
    public PageVO<DrRecordVO> getMedicalRecordList(Long doctorId, Long patientId, Integer page, Integer num,
        Integer relation, Long inquirerId) throws BusinessException {

        //查询全部
        if (relation == null || relation == -1) {
            relation = null;
        }
        List<Long> inquirerIds = null;
        //根据就诊人查询
        if (inquirerId != null) {
            inquirerIds = Lists.newArrayList(inquirerId);
        } else {
            // 根据就诊关系查询
            if (relation != null) {
                inquirerIds = patientFeignClient.getPatientInquirerByRelation(patientId, relation)
                    .stream().map(s -> s.getInquirerId()).collect(Collectors.toList());
            }
        }

        // 查询记录
        List<MedicalRecord> recordList = drRecordDao.queryMedicalRecordList(doctorId, patientId, page, num, relation, inquirerIds);
        // 查询记录数
        Long count = drRecordDao.queryCount(doctorId, patientId, relation, inquirerIds);
        // 装配VO
        List<DrRecordVO> recordVOList = new ArrayList<>();
        //批量获取患者填写量表祥情
        Set<String> extBizIdSet = new HashSet<>();
        for (MedicalRecord medicalRecord : Optional.ofNullable(recordList).orElse(Lists.newArrayList())) {
            if (medicalRecord.getCaseType() != MedicalRecord.CASETYPE_PATIENT_SCALE) {
                continue;
            }
            if (medicalRecord.getRecordScale() == null || medicalRecord.getRecordScale().getExtBizId() == null) {
                LOGGER.info("医生病历中有患者填写量表脏数据");
                continue;
            }
            extBizIdSet.add(medicalRecord.getRecordScale().getExtBizId());
        }
        // 病历记录
        for (MedicalRecord medicalRecord : Optional.ofNullable(recordList).orElse(Lists.newArrayList())) {
            Date date = medicalRecord.getCreateAt();
            if (date == null) {
                LOGGER.warn("创建时间没有，recordId:{}", medicalRecord.getId());
                continue;
            }
            DrRecordVO recordVO = new DrRecordVO();
            BeanUtils.copyProperties(medicalRecord, recordVO);
            //默认不显示作废按钮，因为目前只有先病历后处方的才会有作废按钮
            recordVO.setHospitalName(EHP_HOSPITAL_NAME);
            recordVO.setShowInvalidBtn(1);
            recordVO.setCreateAt(date.getTime());
            Integer caseType = medicalRecord.getCaseType();
            if (caseType == MedicalRecord.CASETYPE_DOCTORRECORD || caseType == MedicalRecord.CASETYPE_DOCTORRECORD_RECOM) {
                // 医生填写病历
                DrCaseVO drCaseVO = this.buildDrRecordVO(medicalRecord, DR_RECORD_SON);
                if (drCaseVO == null) {
                    continue;
                }
                //如果是先病历后处方的，才有作废状态
                if (caseType == MedicalRecord.CASETYPE_DOCTORRECORD_RECOM) {
                    Integer invalid = Optional.ofNullable(drCaseVO.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL);
                    recordVO.setShowInvalidBtn(invalid.equals(MedicalRecord.INVALID_STATUS_NORMAL) ? 0 : 1);
                }
                recordVO.setMdicalRecordVO(drCaseVO);
            } else if (caseType == MedicalRecord.CASETYPE_PATIENTRECORD) {
                // 患者发送病历
                RecordPaitentCaseVO recordPaitentCaseVO = this.buildPtRecordVO(medicalRecord, PT_RECORD_SON);
                if (recordPaitentCaseVO == null) {
                    continue;
                }
                recordVO.setMdicalRecordVO(recordPaitentCaseVO);
            } else if (caseType == MedicalRecord.CASETYPE_RECOM) {
                // 老数据没有单位，默认返回"岁"
                String ageUnit = medicalRecord.getAgeUnit();
                if (StringUtils.isEmpty(ageUnit)) {
                    recordVO.setAgeUnit(MedicalRecord.AgeUnitEunm.YEAR.getUnit());
                }
                // 处方和带基本病情的处方
                RecordPrescriptionVO prescriptionVO = this.buildRecom(medicalRecord);
                if (prescriptionVO == null) {
                    continue;
                }
                recordVO.setMdicalRecordVO(prescriptionVO);
            } else if (caseType == MedicalRecord.CASETYPE_CONSULT) {
                DrCaseVO vo = this.handleConsultRoom(medicalRecord.getRecordConsult(), medicalRecord, PT_CONSULT_ROOM_SON);
                if (vo == null) {
                    continue;
                }
                recordVO.setMdicalRecordVO(vo);

            } else {
                LOGGER.warn("返回病历记录列表有脏数据,recordId:{}", medicalRecord.getId());
                continue;
            }
            //设置病例标签_海南新增
            List<DoctorInfo> doctors = medicalRecord.getDoctors();
            recordVO.setTagsType(doctors.stream().filter(s -> doctorId.equals(s.getDoctorId()))
                .map(s -> s.getRole()).findFirst().get());

            //设置签名信息
            SignInfoVO signInfo = new SignInfoVO();
            if (medicalRecord.getSignInfo() != null) {
                BeanUtil.copyProperties(medicalRecord.getSignInfo(), signInfo);
                if (signInfo.getSealImage() != null) {
                    RecomUserInfoBO userInfoBO = remoter.getUserInfo(medicalRecord.getDoctorId(), null, false);
                    signInfo.setSealImage(userInfoBO.getDoctor().getSealImage());
                }
            }
            recordVO.setSignInfo(signInfo);

            //就诊人与患者关系
            String relationName = InquirerRelationEnum.getNameByValue(medicalRecord.getRelation());
            if (relationName.length() == 2) {
                relationName = "患者" + relationName;

            }
            recordVO.setInquirerRelationName(relationName);
            recordVOList.add(recordVO);
        }
        return PageVO.newBuilder()
            .pageNo(page)
            .pageSize(num)
            .totalCount(count.intValue())
            .result(recordVOList)
            .build();
    }

    @Override
    public PatientOrDoctorCaseVO getPtOrDrMedicalRecord(String id) throws BusinessException {
        MedicalRecord medicalRecord = medicalRecordRepository.get(id);
        Assert.notNull(medicalRecord, String.format("没有查询到病历 recordId:%s", id));
        PatientOrDoctorCaseVO patientOrDoctorCaseVO = new PatientOrDoctorCaseVO();
        patientOrDoctorCaseVO.setRecoreId(id);
        patientOrDoctorCaseVO.setCaseType(medicalRecord.getCaseType());
        //默认不显示作废按钮，因为目前只有先病历后处方的才会有作废按钮
        patientOrDoctorCaseVO.setShowInvalidBtn(1);
        // 医生病历或医生带处方病历
        Integer caseType = patientOrDoctorCaseVO.getCaseType();
        if (caseType == MedicalRecord.CASETYPE_DOCTORRECORD || caseType == MedicalRecord.CASETYPE_DOCTORRECORD_RECOM) {
            DrCaseVO drCaseVO = this.buildDrRecordVO(medicalRecord, DR_RECORD_ALL);
            //如果是先病历后处方的，才有作废状态
            if (caseType == MedicalRecord.CASETYPE_DOCTORRECORD_RECOM) {
                Integer invalid = Optional.ofNullable(drCaseVO.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL);
                patientOrDoctorCaseVO.setShowInvalidBtn(invalid.equals(MedicalRecord.INVALID_STATUS_NORMAL) ? 0 : 1);
            }
            drCaseVO.setMedicalRecordSettingList(medicalRecord.getMedicalRecordSettingList());
            patientOrDoctorCaseVO.setDrCaseVO(drCaseVO);
        } else if (caseType == MedicalRecord.CASETYPE_PATIENTRECORD) {// 患者病历
            patientOrDoctorCaseVO.setPtCaseVO(this.buildPtRecordVO(medicalRecord, PT_RECORD_ALL));
        } else if (caseType == MedicalRecord.CASETYPE_CONSULT) {
            patientOrDoctorCaseVO.setDrCaseVO(this.handleConsultRoom(medicalRecord.getRecordConsult(), medicalRecord, PT_CONSULT_ROOM_ALL));
        }

        //签名信息
        SignInfoVO signInfo = new SignInfoVO();
        if (medicalRecord.getSignInfo() != null) {
            BeanUtil.copyProperties(medicalRecord.getSignInfo(), signInfo);
            if (signInfo.getSealImage() != null) {
                RecomUserInfoBO userInfoBO = remoter.getUserInfo(medicalRecord.getDoctorId(), null, false);
                signInfo.setSealImage(userInfoBO.getDoctor().getSealImage());
                signInfo.setHandWriting(
                    ESignUtils.isHandWriting() ? SignInfoDTO.HANDWRITING_YES : SignInfoDTO.HANDWRITING_NO);
            }
        }
        patientOrDoctorCaseVO.setSignInfo(signInfo);
        return patientOrDoctorCaseVO;
    }

    /**
     * 构建医生填写病历祥情 DrCaseServiceImpl.drMedicalRecordToVO()
     *
     * @param medicalRecord
     * @param flag          ：1全部祥情，2:子祥情
     * @return
     * @throws BusinessException
     * @Author lichaopi
     * @Date 2018年6月30日
     * @since 1.0.0
     */
    private DrCaseVO buildDrRecordVO(MedicalRecord medicalRecord, int flag) throws BusinessException {
        MedicalRecordDoctor medicalRecordDoctor = medicalRecord.getRecordDoctor();
        // 图片
        List<ImgFileVO> imgVOList = Optional.ofNullable(medicalRecordDoctor.getImgList())
            .orElse(Lists.newArrayList())
            .stream()
            .map(img -> new ImgFileVO(img.getUuid(), ImageUrlUtil.getMedicalRecordImg(img.getUrl())))
            .collect(Collectors.toList());
        // double类型转str
        Double temperature = medicalRecordDoctor.getTemperature();// 体温
        String temperatureStr = null;
        if (temperature != null) {
            temperatureStr = String.valueOf(temperature.doubleValue());
        }
        Double weight = medicalRecordDoctor.getWeight();// 体重
        String weightStr = null;
        if (weight != null) {
            weightStr = String.valueOf(weight.doubleValue());
        }

        // 病历祥情
        DrCaseVO drCaseVO = new DrCaseVO();
        //复制患者医生基本数据
        BeanUtils.copyProperties(medicalRecord, drCaseVO);
        //复制患者病历
        BeanUtils.copyProperties(medicalRecordDoctor, drCaseVO);
        drCaseVO.setMoreExamin(medicalRecordDoctor.getMoreExamin());
        MenstrualVO menstrualVO = new MenstrualVO();
        if (null != medicalRecordDoctor.getMenstrual()) {
            BeanUtils.copyProperties(medicalRecordDoctor.getMenstrual(), menstrualVO);
        }
        drCaseVO.setHospitalName(EHP_HOSPITAL_NAME);
        drCaseVO.setMenstrual(menstrualVO);
        drCaseVO.setTemperature(temperatureStr);
        drCaseVO.setWeight(weightStr);
        List<String> diagnosisList = medicalRecordDoctor.getDiagnosisList();
        //drCaseVO.setDiagnosis(diagnosis);
        drCaseVO.setDiagnosisList(diagnosisList);
        drCaseVO.setImgList(imgVOList);
        drCaseVO.setInvalid(Optional.ofNullable(medicalRecord.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL));
        drCaseVO.setInvalidTime(medicalRecord.getInvalidTime());
        drCaseVO.setTemplateId(medicalRecordDoctor.getTemplateId());
        drCaseVO.setTemplateName(medicalRecordDoctor.getTemplateName());
        //判断是否有量表
        if (medicalRecordDoctor.getScale() != null) {
            DoctorScaleVO doctorScaleVo = new DoctorScaleVO();
            doctorScaleVo.setExtBizId(medicalRecordDoctor.getScale().getExtBizId());
            drCaseVO.setDoctorScaleVO(doctorScaleVo);
        }
        //祥情多取的字段
        if (flag == DrCaseServiceImpl.DR_RECORD_ALL) {
            Date date = medicalRecord.getCreateAt();
            String createDate = DateUtil.formatDate(date, "yyyy-MM-dd hh:mm");
            drCaseVO.setCreateDate(createDate);
            drCaseVO.setCreateAt(date.getTime());
            //标准诊断
            drCaseVO.setStandardDiagList(diagnosisList);
            if (diagnosisList != null && !diagnosisList.isEmpty()) {
                //如果是灰度医生，取出icd10诊断
                RecomUserInfoBO remoterUserInfo = remoter.getUserInfo(medicalRecord.getDoctorId(), medicalRecord.getPatientId(), true);
                RecomDoctorBO doctorBO = remoterUserInfo.getDoctor();
                if (doctorBO.getLabel().getDiagnosis()) {
                    RecomDiagnosisBO diagnosisBo = remoter.getRecomICD10(diagnosisList);
                    if (diagnosisBo != null) {
                        drCaseVO.setStandardDiagList(diagnosisBo.getDiagnosis());
                        drCaseVO.setDiagnoseDeleteTip(diagnosisBo.getDiagnoseDeleteTip());
                    }
                }
            }

        }
        // 有推荐类型返回推荐对象
        if (medicalRecord.getCaseType() == MedicalRecord.CASETYPE_DOCTORRECORD_RECOM) {
            if (medicalRecordDoctor.getRecom() != null) {
                RecordPrescriptionVO recordPrescriptionVO = new RecordPrescriptionVO();
                recordPrescriptionVO.setRecommendId(medicalRecordDoctor.getRecom().getRecommendId());
                recordPrescriptionVO.setInvalid(Optional.ofNullable(medicalRecordDoctor.getRecom().getInvalid())
                    .orElse(MedicalRecord.INVALID_STATUS_NORMAL));
                //设置处方图片
                if (recordPrescriptionVO.getInvalid().equals(MedicalRecord.INVALID_STATUS_INVALID)) {
                    recordPrescriptionVO.setUrl(ImageUrlUtil.getMedicalRecordImg(ConfigUtil.getString("prescription.invalid.img.url")));
                } else {
                    recordPrescriptionVO.setUrl(ImageUrlUtil.getMedicalRecordImg(ConfigUtil.getString("prescription.img.url")));
                }
                drCaseVO.setPrescriptionVO(recordPrescriptionVO);
            } else {
                LOGGER.info("带处方病历有脏数据");
            }
        }
        return drCaseVO;
    }

    /**
     * 转患者发送病历VO对象 DrCaseServiceImpl.ptMedicalRecordToVO()
     *
     * @param medicalRecord
     * @return
     * @Author lichaopi
     * @Date 2018年6月6日
     * @since 1.0.0
     */
    private RecordPaitentCaseVO buildPtRecordVO(MedicalRecord medicalRecord, int flag) {
        MedicalRecordFromPatient medicalRecordFromPatient = medicalRecord.getRecordPatient();
        if (medicalRecordFromPatient == null) {
            LOGGER.warn("患者发送病历为空,recordId:{}", medicalRecord.getId());
            return null;
        }

        // 患者病历祥情
        RecordPaitentCaseVO pateintCaseVO = new RecordPaitentCaseVO();
        BeanUtils.copyProperties(medicalRecordFromPatient, pateintCaseVO);
        pateintCaseVO.setMedicAllergys(medicalRecordFromPatient.getMedicAllergysStr());
        pateintCaseVO.setPastDiseases(medicalRecordFromPatient.getPastDiseasesStr());
        pateintCaseVO.setFamilyDiseases(medicalRecordFromPatient.getFamilyDiseasesStr());
        pateintCaseVO.setHereditaryDiseases(medicalRecordFromPatient.getHereditaryDiseasesStr());
        pateintCaseVO.setSmoke(medicalRecordFromPatient.getSmokeStr());
        pateintCaseVO.setDrink(medicalRecordFromPatient.getDrinkStr());

        // 医嘱图片
        List<MCaseFileImgVO> adviceList = Optional.ofNullable(medicalRecordFromPatient.getAdviceList())
            .orElse(Lists.newArrayList())
            .stream()
            .map(img -> new MCaseFileImgVO(img.getUploadTime(), ImageUrlUtil.getCaseImgDomain(img.getImgUrl())))
            .collect(Collectors.toList());
        pateintCaseVO.setAdviceList(adviceList);

        // 处方图片
        List<MCaseFileImgVO> prescriptionList = Optional.ofNullable(medicalRecordFromPatient.getPrescriptionList())
            .orElse(Lists.newArrayList())
            .stream()
            .map(img -> new MCaseFileImgVO(img.getUploadTime(),
                ImageUrlUtil.getCaseImgDomain(img.getImgUrl())))
            .collect(Collectors.toList());
        pateintCaseVO.setPrescriptionList(prescriptionList);

        // 检查单图片
        List<MCaseFileImgVO> checkList = Optional.ofNullable(medicalRecordFromPatient.getCheckList())
            .orElse(Lists.newArrayList())
            .stream()
            .map(img -> new MCaseFileImgVO(img.getUploadTime(), ImageUrlUtil.getCaseImgDomain(img.getImgUrl())))
            .collect(Collectors.toList());
        pateintCaseVO.setCheckList(checkList);
        pateintCaseVO.setInvalid(Optional.ofNullable(medicalRecord.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL));
        if (flag == DrCaseServiceImpl.PT_RECORD_ALL) {// 全部祥情
            Date date = medicalRecord.getCreateAt();
            String createDate = DateUtil.formatDate(date, "yyyy-MM-dd hh:mm");
            BeanUtils.copyProperties(medicalRecord, pateintCaseVO);
            pateintCaseVO.setCreateDate(createDate);
            pateintCaseVO.setCreateAt(date.getTime());
        }
        // 处理换行和回车
        this.handleAmc(pateintCaseVO.getAmcResult());
        // 是否孕期
        Integer pregnancy = medicalRecordFromPatient.getPregnancy();
        if (pregnancy != null && RecordPaitentCaseVO.EPregnancy.val(pregnancy) != null) {
            pateintCaseVO.setPregnancy(RecordPaitentCaseVO.EPregnancy.val(pregnancy).getName());
        }
        return pateintCaseVO;
    }

    @Override
    public MedicalRecordIdBO getMedicalRecordId(Long doctorId, Long patientId) {
        MedicalRecordIdBO medicalRecordIdBO = new MedicalRecordIdBO();
        MedicalRecord medicalRecord = drRecordDao.getPtOrDrSendLateCase(doctorId, patientId,
            MedicalRecord.ERelation.RELATION_ONESELF.getValue());
        if (medicalRecord == null) {
            medicalRecordIdBO.setIdFlag(MedicalRecordIdBO.IDFLAG_NO);
            return medicalRecordIdBO;
        }
        medicalRecordIdBO.setIdFlag(MedicalRecordIdBO.IDFLAG_YES);
        String recordId = medicalRecord.getId();
        medicalRecordIdBO.setId(recordId);
        if (medicalRecord.getCreateAt() == null) {
            LOGGER.warn("病历记录创建时间为空,recordId:{}", recordId);
        } else {
            String dateStr = DateUtil.formatDate(medicalRecord.getCreateAt(), DateUtil.DATE_FORMAT_CN);
            medicalRecordIdBO.setCreateDate(dateStr);
        }
        return medicalRecordIdBO;
    }

    @Override
    public void addMedicalRecordByBO(MedicalRecordBO medicalRecordBO) {

        // 病历记录
        MedicalRecord medicalRecord = new MedicalRecord();
        BeanUtils.copyProperties(medicalRecordBO, medicalRecord);
        medicalRecordBO.setRelation(MedicalRecord.ERelation.RELATION_ONESELF.getValue());

        if (medicalRecordBO.getCaseType() == MedicalRecord.CASETYPE_RECOM) {// 系统处方
            MedicalRecordRecomBO recomBO = medicalRecordBO.getRecordRecom();
            MedicalRecordRecom recom = new MedicalRecordRecom();
            recom.setRecommendId(recomBO.getRecommendId());
            recom.setInvalid(recomBO.getInvalid());
            medicalRecord.setRecordRecom(recom);
        }
        medicalRecordRepository.save(medicalRecord);

    }

    @Override
    public List<MedicalRecordScreenBO> getScreenList(Long doctorId, Long patientId) {
        // 查询筛选条件列表
        List<MedicalRecordScreen> list = medicalRecordScreenRepository.findByDoctorIdAndPatientId(doctorId, patientId);
        List<MedicalRecordScreenBO> boList = new ArrayList<>();
        MedicalRecordScreenBO bo = new MedicalRecordScreenBO(-1, "全部");
        boList.add(bo);
        // 以防有脏数据，手动去重
        List<Integer> valueList = new ArrayList<>();
        // 装配
        Optional.ofNullable(list).orElse(Lists.newArrayList()).forEach(mrc -> {
            if (valueList.contains(mrc.getRelation())) {
                LOGGER.warn("筛选条件有脏数据,doctorId:{},patientId:{},relation:{}", doctorId, patientId, mrc.getRelation());
                return;
            }
            MedicalRecordScreenBO mrsBo = new MedicalRecordScreenBO(mrc.getRelation(), mrc.getRelationName());
            boList.add(mrsBo);
            valueList.add(mrc.getRelation());
        });
        return boList;
    }

    @Override
    @Async
    public void notifyRevisit(Long dId) {
        List<String> drPrIdList = new ArrayList<>();
        String toDayPartKey = DateUtil.formatDate(new Date(), DateUtil.DATE_FORMAT);
        // 今天
        String dayKey = NOTIFY_REVISIT_RECORDID_KEY + toDayPartKey;
        Long length = RedisUtil.listOps().llen(dayKey);
        for (int i = 0; i < length; i++) {
            String revisitStr = RedisUtil.listOps().lindex(dayKey, i);
            // String revisitStr = RedisUtil.listOps().lpop(dayKey);移除元素并返回
            RedisRevisitBO redisRevisitBO;
            try {
                redisRevisitBO = JsonMapper.toObject(revisitStr, RedisRevisitBO.class);
            } catch (JsonException e) {
                LOGGER.error("今天复诊提醒转换json出错,json:{}", revisitStr);
                continue;
            }
            if (redisRevisitBO == null) {
                LOGGER.error("今天复诊提醒转换json为空,json:{}", revisitStr);
                continue;
            }
            // 方便测试
            if (dId != null) {
                if (redisRevisitBO.getDoctorId().longValue() != dId.longValue()) {
                    continue;
                }
            }
            String drPrId = redisRevisitBO.getDoctorId() + "-" + redisRevisitBO.getPatientId();
            if (drPrIdList.contains(drPrId)) {
                LOGGER.info("今天该患者和该医生已发过通知,drPrId:{}", drPrId);
                continue;
            }
            String recoreId = redisRevisitBO.getId();
            MedicalRecord medicalRecord = medicalRecordRepository.get(recoreId);
            Integer invalid = Optional.ofNullable(medicalRecord.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL);
            if (invalid != MedicalRecord.INVALID_STATUS_NORMAL) {
                LOGGER.warn("病历作废，不发送提醒，recoreId:{}", recoreId);
                continue;
            }
            NotifyRevisitBO revisitBO = new NotifyRevisitBO();
            revisitBO.setDoctorId(redisRevisitBO.getDoctorId());
            revisitBO.setPatientId(redisRevisitBO.getPatientId());
            revisitBO.setDoctorName(redisRevisitBO.getDoctorName());
            revisitBO.setPatientName(redisRevisitBO.getPatientName());
            revisitBO.setDayFlag(NotifyRevisitBO.DAYFLAG_TODAY);// 今天
            revisitBO.setRevisitDate(toDayPartKey);
            // 发通知
            try {
                remoter.notifyRevisitIM(revisitBO);
            } catch (Exception e) {
                LOGGER.error("今天复诊提醒调用IM异常,json:{}", revisitStr, e);
                continue;
            }
            drPrIdList.add(drPrId);
        }
    }

    /**
     * 构建处方VO DrCaseServiceImpl.buildRecom()
     *
     * @param medicalRecord
     * @return
     * @Author lichaopi
     * @Date 2018年6月4日
     * @since 1.0.0
     */
    private RecordPrescriptionVO buildRecom(MedicalRecord medicalRecord) {
        MedicalRecordRecom medicalRecordRecom = medicalRecord.getRecordRecom();
        if (medicalRecordRecom == null) {
            LOGGER.warn("系统处方为空,recordId:{}", medicalRecord.getId());
            return null;
        }
        RecordPrescriptionVO recordPrescriptionVO = new RecordPrescriptionVO(medicalRecordRecom.getRecommendId(), null);
        //处方作废
        recordPrescriptionVO.setInvalid(Optional.ofNullable(medicalRecordRecom.getInvalid()).orElse(MedicalRecord.INVALID_STATUS_NORMAL));
        //处方默认图片
        if (recordPrescriptionVO.getInvalid() == MedicalRecord.INVALID_STATUS_INVALID) {
            recordPrescriptionVO.setUrl(ImageUrlUtil.getMedicalRecordImg(ConfigUtil.getString("prescription.invalid.img.url")));
        } else {
            recordPrescriptionVO.setUrl(ImageUrlUtil.getMedicalRecordImg(ConfigUtil.getString("prescription.img.url")));
        }
        return recordPrescriptionVO;
    }

    /**
     * 处理换行。 DrCaseServiceImpl.handleAmc()
     *
     * @param result
     * @Author lichaopi
     * @Date 2018年6月11日
     * @since 1.0.0
     */
    private void handleAmc(AmcResultVO result) {
        if (result == null) {
            return;
        }
        String inquirySymptom = result.getInquirySymptom();
        if (StringUtils.isNotEmpty(inquirySymptom)) {
            result.setInquirySymptom(inquirySymptom.replaceAll("\\r|\\n", ""));
        }
        List<ConclusionVO> list = result.getConclusions();
        Optional.ofNullable(list).orElse(Lists.newArrayList()).forEach(conclusionVO -> {
            if (StringUtils.isNotEmpty(conclusionVO.getTitle())) {
                conclusionVO.setTitle(conclusionVO.getTitle().replaceAll("\\r|\\n", ""));
            }
            if (StringUtils.isNotEmpty(conclusionVO.getContent())) {
                conclusionVO.setContent(conclusionVO.getContent().replaceAll("\\r|\\n", ""));
            }
        });
    }

    @Override
    public DrRecordIdBO saveDrRecordTemporary(DrCaseParams params) throws BusinessException {
        DrRecordIdBO recordIdBO = new DrRecordIdBO();
        // 验证并装配数据
        MedicalRecord medicalRecord = this.drCaseToMedicalRecord(params);
        // 保存病历
        medicalRecordRepository.save(medicalRecord);

        PatientMedicalRecord patientMedicalRecord;
        try {
            patientMedicalRecord = this.buildPatientCase(medicalRecord, Constants.CASE_STATUS_TEMPORARY);// 暂存
            patientMedicalRecordRepository.save(patientMedicalRecord);
        } catch (Exception e) {
            LOGGER.warn("保存患者发送病历异常", e);
            medicalRecordRepository.remove(medicalRecord);
            LOGGER.info("异常成功删除病历记录");
            throw new BusinessException(ExceptionCodes.FAILED, e);
        }
        recordIdBO.setRecordId(medicalRecord.getId());
        // 更新复诊时间和诊断结果
        patientIntelligentLabelService.updateRevisitTimeAndDiagnosis(medicalRecord);
        return recordIdBO;
    }

    @Override
    public MedicalRecordDoctorBO getDrRecordBOMessage(Long recommendId) {
        MedicalRecord medicalRecord = medicalRecordRepository.getMRByRecomId(recommendId);
        // 查询患者病历
        if (medicalRecord == null) {
            return null;
        }
        MedicalRecordDoctorBO medicalRecordDoctorBO = this.buildRecordMessageBO(medicalRecord);
        // 查询患者病历
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByDrRecordId(medicalRecord.getId());
        if (patientMedicalRecord != null) {
            medicalRecordDoctorBO.setPtRecordId(patientMedicalRecord.getId());
        }
        return medicalRecordDoctorBO;
    }

    /**
     * 构建Im病历消息 DrCaseServiceImpl.buildImRecordMessage()
     *
     * @param medicalRecord
     * @return
     * @since 1.0.0
     */
    private DoctorsMedicalRecordBO buildImRecordMessage(MedicalRecord medicalRecord) {
        DoctorsMedicalRecordBO doctorsMedicalRecordBO = new DoctorsMedicalRecordBO();
        MedicalRecordDoctorBO medicalRecordDoctorBO = this.buildRecordMessageBO(medicalRecord);
        //复制属性
        BeanUtils.copyProperties(medicalRecordDoctorBO, doctorsMedicalRecordBO);
        doctorsMedicalRecordBO.setMedicalRecordId(medicalRecordDoctorBO.getRecordId());// 病历id
        doctorsMedicalRecordBO.setDoctorHospital(medicalRecordDoctorBO.getHospitalName());// 医院姓名
        doctorsMedicalRecordBO.setInquirerId(medicalRecord.getInquirerId());// 医院姓名
        doctorsMedicalRecordBO.setPatientGender(medicalRecordDoctorBO.getGenderName());// 性别
        doctorsMedicalRecordBO.setAge(medicalRecordDoctorBO.getAgeStr());// 年龄
        doctorsMedicalRecordBO.setDoctorTitle(medicalRecordDoctorBO.getTitle());// 职称
        doctorsMedicalRecordBO.setDoctorsSummary(medicalRecordDoctorBO.getPatientOrder());// 医嘱内容
        return doctorsMedicalRecordBO;
    }

    /**
     * 构建病历消息BO DrCaseServiceImpl.buildRecordMessage()
     *
     * @param medicalRecord
     * @return
     * @since 1.0.0
     */
    private MedicalRecordDoctorBO buildRecordMessageBO(MedicalRecord medicalRecord) {
        MedicalRecordDoctorBO medicalRecordDoctorBO = new MedicalRecordDoctorBO();
        medicalRecordDoctorBO.setRecordId(medicalRecord.getId());
        MedicalRecordDoctor recordDoctor = medicalRecord.getRecordDoctor();
        MedicalRecordRecom medicalRecordRecom = recordDoctor.getRecom();
        if (medicalRecordRecom != null) {
            medicalRecordDoctorBO.setRecommendId(medicalRecordRecom.getRecommendId());
        }
        BeanUtils.copyProperties(medicalRecord, medicalRecordDoctorBO);
        medicalRecordDoctorBO.setPatientName(medicalRecord.getName());

        Integer gender = medicalRecord.getGender();
        medicalRecordDoctorBO.setGender(gender);
        medicalRecordDoctorBO.setGenderName(MedicalRecord.GenderEnum.val(gender).getName());

        // 主诉截取100个字符
        String mainComplaint = recordDoctor.getMainComplaint();
        medicalRecordDoctorBO.setMainComplaint(mainComplaint);
        if (mainComplaint != null && mainComplaint.length() > 100) {
            medicalRecordDoctorBO.setMainComplaint(mainComplaint.substring(0, 99));
        }
        // 诊断
        List<String> diagnosisList = recordDoctor.getDiagnosisList();
        medicalRecordDoctorBO.setDiagnosis(this.buildDiagnosis(diagnosisList));
        // 拼装医嘱内容
        this.buildOrder(medicalRecord, medicalRecordDoctorBO);
        return medicalRecordDoctorBO;
    }

    /**
     * 诊断列表转换成字符串 DrCaseServiceImpl.buildDiagnosis()
     *
     * @param diagnosisList
     * @return
     * @Author lichaopi
     * @Date 2018年6月28日
     * @since 1.0.0
     */
    private String buildDiagnosis(List<String> diagnosisList) {
        return Joiner.on(",").skipNulls().join(Optional.ofNullable(diagnosisList).orElse(Lists.newArrayList()));
    }


    /**
     * 拼装患者端和医生端医嘱内容 DrCaseServiceImpl.buildOrder()
     *
     * @param medicalRecord
     * @return
     * @Author lichaopi
     * @Date 2018年6月28日
     * @since 1.0.0
     */
    private void buildOrder(MedicalRecord medicalRecord, MedicalRecordDoctorBO medicalRecordDoctorBO) {
        // 处方字符串
        String recomStr = ConfigUtil.getString("patient.recom.text");// 请按医嘱购药后服用
        String reversitFormat = ConfigUtil.getString("reversit.text");// 下次复诊....
        String messageStr = ConfigUtil.getString("record.message.text");// 我为你写了一份...
        // 复诊字符串
        String reversit = "";
        // 判断有无复诊时间
        MedicalRecordDoctor medicalRecordDoctor = medicalRecord.getRecordDoctor();
        if (medicalRecordDoctor.getRevisitFalg() == MedicalRecordDoctor.REVISITFALG_YES) {
            Integer number = medicalRecordDoctor.getRevisitNumber();// 几天、几周后
            String dateUnit = medicalRecordDoctor.getRevisitDateUnit();
            if (Objects.equals(dateUnit, MedicalRecordDoctor.DATE_UNTI_MONTH)) {
                dateUnit = "个" + dateUnit;
            }
            String revisitDate = DateUtil.formatDate(medicalRecordDoctor.getRevisitDate(), DateUtil.DATE_FORMAT_CN);
            reversit = String.format(reversitFormat, number, dateUnit, revisitDate);
        }
        // 医嘱小结
        String orderStr = "";
        if (medicalRecordDoctor.getDoctorOrder() != null) {
            orderStr = medicalRecordDoctor.getDoctorOrder();
            // 超过100字符串，截取
            if (orderStr.length() > 100) {
                orderStr = orderStr.substring(0, 99);
            }
        }
        String patientOrder;// 医嘱内容
        Integer displayType; // 病历类型
        // 没有处方
        if (medicalRecord.getRecordDoctor().getRecom() == null) {
            // 患者医嘱内容
            patientOrder = reversit + orderStr;
            // 当没有复诊时间和医嘱小结时，加一段文字
            if (StringUtils.isEmpty(patientOrder)) {
                patientOrder = messageStr;
            }
            // 病历类型
            if (!StringUtils.isEmpty(reversit) && !StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_FIFTH;// 复诊+医嘱小结
            } else if (!StringUtils.isEmpty(reversit) && StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_SIXTH;// 复诊
            } else if (StringUtils.isEmpty(reversit) && !StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_SEVENTH;// 医嘱小结
            } else {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_ETGHTH;//
            }
        } else {// 有处方
            // 患者医嘱内容
            patientOrder = recomStr + reversit + orderStr;
            // 病历类型
            if (!StringUtils.isEmpty(reversit) && !StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_FIRST;// 处方+复诊+医嘱小结
            } else if (!StringUtils.isEmpty(reversit) && StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_SECOND;// 处方+复诊
            } else if (StringUtils.isEmpty(reversit) && !StringUtils.isEmpty(orderStr)) {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_THIRD;// 处方+医嘱小结
            } else {
                displayType = DoctorsMedicalRecordBO.MEDICAL_DISPLAY_TYPE_FOURTH;// 处方
            }

        }
        medicalRecordDoctorBO.setDisplayType(displayType);
        medicalRecordDoctorBO.setPatientOrder(patientOrder);
    }


    @Override
    public void updateDrCase(String recordId) throws BusinessException {
        // 查询病历
        MedicalRecord medicalRecord = medicalRecordRepository.get(recordId);
        Assert.notNull(medicalRecord, String.format("没有查询到病历 recordId:%s", recordId));
        // 更新病历状态（去掉暂存）
        medicalRecord.setTemporary(null);
        // 已发送标识
        medicalRecord.setSend(MedicalRecord.SEND_YES);
        medicalRecordRepository.update(medicalRecord);
        // 判断病历页筛选条件是否已存在
        super.saveMedicalRecordScreen(medicalRecord);
        // 更新患者发送病历状态
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByDrRecordId(medicalRecord.getId());
        try {
            if (patientMedicalRecord == null) {
                LOGGER.warn("查询患者发送病历为空,drRecordId:{}", medicalRecord.getId());
                throw new BusinessException(ExceptionCodes.FAILED);
            }
            patientMedicalRecord.setStatus(Constants.CASE_STATUS_FINISH);
            patientMedicalRecordRepository.update(patientMedicalRecord);
        } catch (Exception e) {
            LOGGER.warn("更新医生发送病历错误", e);
            medicalRecord.setTemporary(MedicalRecord.TEMPORARY_YES);
            medicalRecord.setSend(null);
            medicalRecordRepository.update(medicalRecord);
            LOGGER.info("异常成功更新病历记录为暂存");
            throw new BusinessException(ExceptionCodes.FAILED, e);
        }

        // 保存redis复诊时间
        try {
            this.setRecordKey(medicalRecord);
        } catch (Exception e) {
            LOGGER.warn("保存医生发送病历错误", e);
            medicalRecord.setTemporary(MedicalRecord.TEMPORARY_YES);
            medicalRecord.setSend(null);
            medicalRecordRepository.update(medicalRecord);
            LOGGER.info("异常成功更新病历记录为暂存");
            patientMedicalRecord.setStatus(Constants.CASE_STATUS_TEMPORARY);
            patientMedicalRecordRepository.update(patientMedicalRecord);
            LOGGER.info("异常成功还原医生发送病历");
            throw new BusinessException(ExceptionCodes.FAILED, e);
        }
    }

    /**
     * 构造医生发送病历 DrCaseServiceImpl.buildPatientCase()
     *
     * @param medicalRecord
     * @return
     * @Author lichaopi
     * @Date 2018年6月28日
     * @since 1.0.0
     */
    private PatientMedicalRecord buildPatientCase(MedicalRecord medicalRecord, Integer status) {
        PatientMedicalRecord patientMedicalRecord = new PatientMedicalRecord();
        BeanUtils.copyProperties(medicalRecord, patientMedicalRecord);
        patientMedicalRecord.setId(null);//清空id
        patientMedicalRecord.setDepartmentName(medicalRecord.getDepartment());//科室
        patientMedicalRecord.setSource(Constants.CASE_SOURCE_DOCTOR);// 医生填写病历
        patientMedicalRecord.setStatus(status);// 是否暂存
        patientMedicalRecord.setDrRecordId(medicalRecord.getId());// 病历id
        patientMedicalRecord.setFinishTime(medicalRecord.getCreateAt().getTime());
        patientMedicalRecord.setDoctorMedicalRecord(medicalRecord.getRecordDoctor());// 医生填写病历
        return patientMedicalRecord;
    }

    @Override
    public boolean getRevisitInfo(RevisitNoticeParamBO revisitNoticeParamBO) {
        Date startTime = DateUtil.parseStrToDateTime(revisitNoticeParamBO.getStartTime());
        Date endTime = DateUtil.parseStrToDateTime(revisitNoticeParamBO.getEndTime());
        Long doctorId = revisitNoticeParamBO.getDoctorId();
        Long patientId = revisitNoticeParamBO.getPatientId();
        List<MedicalRecord> revisitList = drRecordDao.getRevisitInfoList(doctorId, patientId, startTime, endTime);
        return !CollectionUtil.isEmpty(revisitList);
    }

    /**
     * 图片复制处理 DrCaseServiceImpl.handleImgList()
     *
     * @param doctorId
     * @param imgList
     * @return
     * @throws Exception
     * @Author lichaopi
     * @Date 2018年6月29日
     * @since 1.0.0
     */
    private List<String> handleImgList(Long doctorId, List<String> imgList) throws Exception {
        List<String> list = new ArrayList<>();
        String url = ConfigUtil.getString("emr.img.url");
        String dir = ImageUtil.getBaseUpload(Constants.RECORD_TYPE);
        for (String imgStr : Optional.ofNullable(imgList).orElse(Lists.newArrayList())) {
            if (imgStr.contains(url)) {// 有域名
                // 读取图片
                File file = new File(dir + imgStr.replace(url, ""));
                if (!file.exists()) {
                    LOGGER.info("图片文件不存在,imgUrl:{}", imgStr);
                    throw new IllegalArgumentException(String.format("图片文件不存在,imgUrl:%s", imgStr));
                }
                // 图片转换成MultipartFile
                MultipartFile mFile = File2MultipartFileUtil.convert(file);
                // 图片上传
                String imgUrl = ImageUtil.getUri(ImageUtil.upload(Constants.RECORD_TYPE, mFile, doctorId), Constants.RECORD_TYPE);
                list.add(imgUrl);
            } else {
                list.add(imgStr);
            }
        }
        return list;
    }

    @Override
    public PatientOrDoctorCaseVO getLateRecord(Long doctorId, Long patientId) throws BusinessException {
        MedicalRecord medicalRecord = drRecordDao.getPtOrDrSendLateCase(doctorId, patientId, null);
        PatientOrDoctorCaseVO patientOrDoctorCaseVO = new PatientOrDoctorCaseVO();
        if (medicalRecord == null) {
            patientOrDoctorCaseVO.setCaseType(PatientOrDoctorCaseVO.CASE_TYPE_NO);
            LOGGER.debug("最近病历为空 doctorId:{} patientId:{}", doctorId, patientId);
            return patientOrDoctorCaseVO;
        }
        patientOrDoctorCaseVO.setCaseType(medicalRecord.getCaseType());
        // 医生病历或医生带处方病历
        Integer caseType = patientOrDoctorCaseVO.getCaseType();
        switch (caseType) {
            case MedicalRecord.CASETYPE_DOCTORRECORD:
                patientOrDoctorCaseVO.setDrCaseVO(this.buildDrRecordVO(medicalRecord, DR_RECORD_ALL));
                break;
            case MedicalRecord.CASETYPE_DOCTORRECORD_RECOM:
                patientOrDoctorCaseVO.setDrCaseVO(this.buildDrRecordVO(medicalRecord, DR_RECORD_ALL));
                break;
            case MedicalRecord.CASETYPE_PATIENTRECORD: // 患者病历
                patientOrDoctorCaseVO.setPtCaseVO(this.buildPtRecordVO(medicalRecord, PT_RECORD_ALL));
                break;
            case MedicalRecord.CASETYPE_CONSULT: // 线上诊室病历
                patientOrDoctorCaseVO.setDrCaseVO(this.handleConsultRoom(medicalRecord.getRecordConsult(), medicalRecord, PT_CONSULT_ROOM_ALL));
                break;
            default:
                LOGGER.warn("病历类型不匹配 caseId:{} caseType:{}", medicalRecord.getId(), caseType);
        }
        return patientOrDoctorCaseVO;
    }

    @Override
    public List<RecordRecomIdBO> getRecordRecomIdBO(List<Long> recomIdList) {
        List<MedicalRecord> mrList = drRecordDao.getRecordListByRecomIdList(recomIdList);
        Function<MedicalRecord, RecordRecomIdBO> medicalRecordRecordRecomIdBOFunction = medicalRecord -> {
            RecordRecomIdBO recordRecomIdBO = new RecordRecomIdBO();
            recordRecomIdBO.setRecordId(medicalRecord.getId());
            recordRecomIdBO.setRecomId(medicalRecord.getRecordDoctor().getRecom().getRecommendId());
            return recordRecomIdBO;
        };
        return Optional.ofNullable(mrList).orElse(Lists.newArrayList())
            .stream()
            .map(medicalRecordRecordRecomIdBOFunction)
            .collect(Collectors.toList());
    }

    @Override
    public void updatePrescriptionStatus(Long doctorId, Long recommendId, Integer invalidStatus) {
        MedicalRecord medicalRecord = medicalRecordRepository.findByDoctorIdAndRecommendId(doctorId, recommendId);
        Assert.notNull(medicalRecord, String.format("没有查询到病历信息，doctorId : %s recommendId : %s", doctorId, recommendId));
        String drRecordId = medicalRecord.getId();
        Integer caseType = medicalRecord.getCaseType();
        if (MedicalRecord.CASETYPE_DOCTORRECORD_RECOM == caseType) {
            //设置病历中处方状态
            medicalRecord.getRecordDoctor().getRecom().setInvalid(invalidStatus);
            PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByDrRecordId(drRecordId);
            MedicalRecordDoctor medicalRecordDoctor = patientMedicalRecord.getDoctorMedicalRecord();
            MedicalRecordRecom medicalRecordRecom = medicalRecordDoctor.getRecom();
            medicalRecordRecom.setInvalid(invalidStatus);
            patientMedicalRecordRepository.update(patientMedicalRecord);
        } else {
            MedicalRecordRecom recordRecom = medicalRecord.getRecordRecom();
            recordRecom.setInvalid(invalidStatus);
        }
        medicalRecordRepository.update(medicalRecord);
    }

    @Override
    public DrCaseInvalidVO updateDrCaseStatus(Long doctorId, String recordId, Integer invalidStatus) throws BusinessException {
        MedicalRecord medicalRecord = medicalRecordRepository.get(recordId);
        if (medicalRecord == null) {
            LOGGER.warn("没有查询到病历信息，doctorId = {} recordId = {}", doctorId, recordId);
            throw new BusinessException(BaseExceptionCodes.FAILED);
        }
        if (Objects.equals(medicalRecord.getInvalid(), invalidStatus)) {
            LOGGER.warn("病历当前作废状态和需要修改状态一致，不更新病历状态 recordId = {}", recordId);
            return new DrCaseInvalidVO(recordId, medicalRecord.getInvalid(), medicalRecord.getInvalidTime());
        }
        medicalRecord.setInvalid(invalidStatus);
        medicalRecord.setInvalidTime(new Date());
        medicalRecordRepository.update(medicalRecord);

        //更新患者病历作废状态
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByDrRecordId(recordId);
        patientMedicalRecord.setInvalid(medicalRecord.getInvalid());
        patientMedicalRecord.setInvalidTime(medicalRecord.getInvalidTime());
        patientMedicalRecordRepository.update(patientMedicalRecord);

        //删除X天复诊智能标签
        PatientIntelligentLabelUtil.removeRevisitTime(doctorId, patientMedicalRecord.getPatientId());
        //更新消息卡片状态
        RecommandDrugBO recommandDrugBO = new RecommandDrugBO();
        //病历ID
        recommandDrugBO.setMedicalRecordId(recordId);
        //病历作废状态
        recommandDrugBO.setInvalid(medicalRecord.getInvalid());
        String noticeRecordImUrl = ConfigUtil.getString("notice.record.invalid");
        RestHttpUtil.post().url(noticeRecordImUrl).body(JsonMapper.toJson(recommandDrugBO)).asyncExecuteData();
        return new DrCaseInvalidVO(recordId, medicalRecord.getInvalid(), medicalRecord.getInvalidTime());
    }

    @Override
    public List<RecordTemplateVO> getTemplateList() {
        Sort sort = Sort.by(Sort.Direction.ASC, "sort");
        Iterable<EmrRecordTemplate> templateList = emrRecordTemplateRepository.findAll(sort);
        List<RecordTemplateVO> templateVoLis = new ArrayList<>();
        templateList.forEach(template -> {
            RecordTemplateVO recordTemplateVO = new RecordTemplateVO();
            BeanUtils.copyProperties(template, recordTemplateVO);
            templateVoLis.add(recordTemplateVO);
        });
        return templateVoLis;
    }

    /**
     * 处理线上诊室病历 DrCaseServiceImpl.handleConsultRoom()
     *
     * @param medicalRecordConsultRoom
     * @param medicalRecord
     * @return
     * @Author lichaopi
     * @Date 2018年9月12日
     * @since 1.0.0
     */
    private DrCaseVO handleConsultRoom(MedicalRecordConsultRoom medicalRecordConsultRoom, MedicalRecord medicalRecord, int flag) {
        if (medicalRecordConsultRoom == null) {
            LOGGER.info("线上认定病历为空");
            return null;
        }
        DrCaseVO recordVO = new DrCaseVO();
        if (flag == PT_CONSULT_ROOM_ALL) {
            BeanUtils.copyProperties(medicalRecord, recordVO);
            recordVO.setCreateAt(medicalRecord.getCreateAt().getTime());
            String createDate = DateUtil.formatDate(medicalRecord.getCreateAt(), "yyyy-MM-dd hh:mm");
            recordVO.setCreateDate(createDate);
        }
        // 默认普通模板
        recordVO.setTemplateType(MedicalRecordDoctor.TEMPLATE_TYPE_COMMON);
        // 装配主诉,咨询主题>病情主诉>患病时长>用药情况
        recordVO.setMainComplaint(super.getMainComplaint(medicalRecordConsultRoom));
        // 装配既往史,既往病史>药物过敏史
        recordVO.setPastHistory(super.getPastHistory(medicalRecordConsultRoom));
        // 装配舒张压和收缩压和医嘱小结
        Integer type = Optional.ofNullable(medicalRecordConsultRoom.getType()).orElse(BaseMedicalRecordConsultRoom.CONSULT_ROOM_TYPE_OLD);
        if (type == BaseMedicalRecordConsultRoom.CONSULT_ROOM_TYPE_OLD) {
            recordVO.setDiastole(medicalRecordConsultRoom.getDiastole());
            recordVO.setSystolic(medicalRecordConsultRoom.getSystolic());
        }
        recordVO.setDoctorOrder(medicalRecordConsultRoom.getTreatment());
        // 组装图片地址
        List<ImgFileVO> imgListVo = Optional.ofNullable(medicalRecordConsultRoom.getImgList()).orElse(Lists.newArrayList())
            .stream()
            .map(imgFile -> ImageUrlUtil.getCaseImgDomain(imgFile.getImgUrl()))
            .map(url -> new ImgFileVO(null, url))
            .collect(Collectors.toList());
        recordVO.setImgList(imgListVo);
        recordVO.setMedicalRecordSettingList(medicalRecord.getMedicalRecordSettingList());
        return recordVO;
    }

    /**
     * 获取患者首聊：病情描述、病历描述文案
     *
     * @param doctorId
     * @param patientId
     * @param type
     * @param recordId
     * @return
     */
    @Override
    public String getDiseaseContent(Long doctorId, Long patientId, Long inquirerId, Integer type, String recordId) {

        String content = "";
        PatientInquirerBO inquirer = null;
        try {
            // 就诊人信息
            List<PatientInquirerBO> patientInquirerBOS = patientFeignClient.getPatientInquirer(Arrays.asList(inquirerId));
            inquirer = patientInquirerBOS.get(0);
        } catch (BusinessException e) {
            LOGGER.info("获取就诊人信息异常 {}", e);
        }

        switch (type) {

            case Constants.PATIENT_CONSULT_TYPE_MEDICATRECORD:
                MedicalRecord medicalRecord = medicalRecordRepository.get(recordId);

                if (medicalRecord != null && medicalRecord.getRecordDoctor() != null) {
                    /*
                    病历详情
                    ----------
                    【患者】姓名  性别  年龄+年龄单位
                    【主诉】
                    【现病史】
                    【既往史】
                    【诊断】
                     紧急联系人：xxx
                     紧急联系人手机：xxx
                    */
                    String name = medicalRecord.getName();
                    String gender = MedicalRecord.GenderEnum.val(medicalRecord.getGender()).getName();
                    String age = medicalRecord.getAgeStr();
                    String patientInfo = "【患者】" + String.join("\t", name, gender, age);
                    String mainComplaint = "【主诉】" + Optional.ofNullable(medicalRecord.getRecordDoctor().getMainComplaint()).orElse("");
                    String preDisease = "【现病史】" + Optional.ofNullable(medicalRecord.getRecordDoctor().getPresentDisease()).orElse("");
                    String pastHistory = "【既往史】" + Optional.ofNullable(medicalRecord.getRecordDoctor().getPastHistory()).orElse("");
                    List<String> diagnosisList = medicalRecord.getRecordDoctor().getDiagnosisList();
                    String diagnosis = "【诊断】" + String.join(",", Optional.ofNullable(diagnosisList).orElse(Collections.emptyList()));
                    String contactName = "【紧急联系人姓名】：" + Optional.ofNullable(medicalRecord.getRecordDoctor().getContactName()).orElse("");
                    String contactPhone = "【紧急联系人手机】：" + Optional.ofNullable(medicalRecord.getRecordDoctor().getContactPhone()).orElse("");
                    content = String.join("<br/>", "病历详情", "--------------------", patientInfo, mainComplaint, preDisease, pastHistory, diagnosis,
                        contactName, contactPhone);
                }

                break;
            case Constants.PATIENT_CONSULT_TYPE_DISEASE:
                PatientDisease patientDisease = patientDiseaseRepository.get(recordId);
                if (patientDisease != null) {
                    /*
                    问诊病情
                    ----------
                    就诊人：xxx
                    线下诊断：xxx
                    病情描述：xxx
                    过敏史：xxx
                    既往史：xxx
                    */
                    // String gender = MedicalRecord.GenderEnum.val(patientDisease.getPatientGender()).getName();
                    String age = patientDisease.getPatientAgeStr();
                    String patientInfo = "就诊人：" + String.join("\t", Optional.ofNullable(inquirer.getName()).orElse(""));
                    String diagnosis = "线下诊断：" + String.join("\t", Optional.ofNullable(patientDisease.getOfflineDiagnosis()).orElse(""));
                    String preDisease = "病情描述：" + Optional.ofNullable(patientDisease.getOfflineDiagnosis()).orElse("");
                    String pastHistory = "过敏史：" + (StringUtils.isBlank(inquirer.getAllergy()) ? "无" : inquirer.getAllergy());
                    String contactName = "既往史：" + (StringUtils.isBlank(inquirer.getPastHistory()) ? "无" : inquirer.getPastHistory());
                    String offlineDoctorInfo = String.join("|", patientDisease.getOfflineHospital(), patientDisease.getOfflineDepartment(),
                        patientDisease.getOfflineDoctor());
                    /*content = String
                        .join("<br/>", "问诊病情", "--------------------", patientInfo, diagnosis, preDisease, pastHistory, contactName, contactPhone,
                            "--------------------",
                            DateUtil.formatDate(patientDisease.getCreateAt(), DateUtil.DATE_TIME_FORMAT), "--------------------",
                            offlineDoctorInfo);*/
                    content = String
                        .join("<br/>", "问诊病情", "--------------------", patientInfo, diagnosis, preDisease, pastHistory, contactName);
                    LOGGER.info("患者首聊：患者填写病情描述 pastHistory={},contactName={},content={}",pastHistory,contactName,content);
                }
                break;

            default:
                LOGGER.error("获取患者首聊：病情描述、病历描述文案失败， doctorId={},patientId={},type={},recordId={}", doctorId, patientId, type, recordId);
                break;
        }

        return content;
    }

    @Override
    public Boolean getCaseExist(Long patientId, Long doctorId) {

        List<Integer> caseList = new ArrayList<>();
        //纯手填病历才视为医生填写病历
        caseList.add(MedicalRecord.CASETYPE_DOCTORRECORD);

        return medicalRecordRepository.existMedicalRecordByPatient(doctorId, patientId, caseList);
    }

    @Override
    public InquireCaseBO inquirerCaseInfo(String recordId) throws BusinessException {
        MedicalRecord record = medicalRecordRepository.get(recordId);
        if (record == null) {
            throw new BusinessException(ExceptionCodes.RECORD_NOT_EXIST);
        }
        return InquireCaseBO.builder()
            .inquirerId(record.getInquirerId())
            .diagnosis(record.getRecordDoctor().getDiagnosisList())
            .build();
    }

    public AddPatientRecordInitializeVO getAddRecordInitializerInfo(String sessionId) {
        return null;
    }
}
